#pragma once

#include <string>
#include <vector>

#if defined(__linux__)
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#elif defined(_WIN32) || defined(_WIN64)
#include <Windows.h>
#include <direct.h>
#endif

#include "os/path/path.hpp"

/* declare */
namespace os {
    bool makedirs(const std::string& path, bool exist_ok = true);
    std::vector<std::string> listdir(const std::string& path);
}

/* define */
namespace os {
    inline bool makedirs(const std::string& path, bool exist_ok) {
        // 如果路径已存在
        if (os::path::exists(path)) {
            // 如果允许已存在则返回true，否则返回false
            return exist_ok;
        }
        
        // 获取父目录路径
        std::string parent = os::path::dirname(path);
        
        // 如果父目录不为空且不存在，则递归创建父目录
        if (!parent.empty() && !os::path::exists(parent)) {
            if (!makedirs(parent, true)) {
                return false;
            }
        }
        
        // 创建当前目录
#if defined(__linux__)
        // 在 Linux 下使用 mkdir 函数创建文件夹
        // 使用 S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH 参数设置权限为 rwxr-xr-x
        return mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0;
#elif defined(_WIN32) || defined(_WIN64)
        // 在 Windows 下使用 _mkdir 函数创建文件夹（注意函数名差异）
        return _mkdir(path.c_str()) == 0;
#else
        // 不支持的系统
        return false;
#endif
    }
    
    inline std::vector<std::string> listdir(const std::string& path) {
        std::vector<std::string> result;
        
        // 检查路径是否存在且为目录
        if (!os::path::exists(path)) {
            // 不支持的系统或路径不存在
#if defined(__linux__) || defined(_WIN32) || defined(_WIN64)
            return result;
#else
            return result;
#endif
        }
        
#if defined(__linux__)
        DIR* dir = opendir(path.c_str());
        if (dir) {
            struct dirent* entry;
            while ((entry = readdir(dir)) != nullptr) {
                std::string name = entry->d_name;
                // 跳过当前目录和父目录
                if (name != "." && name != "..") {
                    result.push_back(name);
                }
            }
            closedir(dir);
        }
#elif defined(_WIN32) || defined(_WIN64)
        WIN32_FIND_DATAA findData;
        HANDLE hFind = FindFirstFileA((path + "\\*").c_str(), &findData);
        
        if (hFind != INVALID_HANDLE_VALUE) {
            do {
                std::string name = findData.cFileName;
                // 跳过当前目录和父目录
                if (name != "." && name != "..") {
                    result.push_back(name);
                }
            } while (FindNextFileA(hFind, &findData));
            
            FindClose(hFind);
        }
#else
        // 不支持的系统
        return result;
#endif
        
        return result;
    }
}